package images;

import game.Configurations;
import game.Units;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.FloatBuffer;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.FixtureDef;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

/**
 *
 * @author Luan
 */
public class ImageManager {
    
    private static String path;
    private static String[] texturePacks;
    private static int ct;
    
    private static Program gray;
    private static boolean grayBinded;
    
    public static void load(String path) {
        ImageManager.path = path;
        File[] tps = new File(path).listFiles();
        texturePacks = new String [tps.length];
        ct = 0;
        for (int i = 0; i < tps.length; i++) {
            texturePacks[i] = tps[i].getName();
            if (texturePacks[i].equals(Configurations.TEXTURE_PACK))
                ct = i;
        }
    }
    
    public static String getString(JSONArray arr, int pos, String t) {
        return ((JSONObject) arr.get(pos)).get(t).toString();
    }
    
    public static int getInt(JSONArray arr, int pos, String t) {
        try {
            return Integer.parseInt(((JSONObject) arr.get(pos)).get(t).toString());
        } catch (NullPointerException ex) {
            return 0; //not specified
        }
    }
    
    public static float getFloat(JSONArray arr, int pos, String t) {
        try {
            return Float.parseFloat(((JSONObject) arr.get(pos)).get(t).toString());
        } catch (NullPointerException ex) {
            return 0; //not specified
        }
    }
    
    public static float[][] getFloats2(JSONArray arr, int pos, String t) {
        try {
            float[][] fs;
            JSONArray ar = (JSONArray) ((JSONObject) arr.get(pos)).get(t);
            fs = new float[ar.size()][];
            for (int i = 0; i < ar.size(); i++) {
                JSONArray ari = ((JSONArray) ar.get(i));
                fs[i] = new float [ari.size()];
                for (int j = 0; j < ari.size(); j++)
                    fs[i][j] = Float.parseFloat(ari.get(j).toString());
            }
            return fs;
        } catch (NullPointerException ex) {
            return null; //not specified
        }
    }
    
    public static FixtureDef getFixture(JSONArray arr, int pos) {
        FixtureDef fd = new FixtureDef();
        fd.density = getFloat(arr, pos, "density");
        fd.friction = getFloat(arr, pos, "friction");
        fd.restitution = getFloat(arr, pos, "restitution");
        
        PolygonShape ps = new PolygonShape();
        JSONArray poly = ((JSONArray) ((JSONObject) arr.get(pos)).get("poly"));
        Vec2[] vs = new Vec2[poly.size()];
        for (int i = 0; i < vs.length; i++) //convert from pixels to meters
            vs[i] = new Vec2(Units.getRealSize(getInt(poly, i, "x")), Units.getRealSize(getInt(poly, i, "y")));
        ps.set(vs, vs.length);
        fd.shape = ps;
        return fd;
    }
    
    public static ImageInfo getImage(JSONArray arr, int pos, double pwx, double pwy) {
        return new ImageInfo(getInt(arr, pos, "x"), getInt(arr, pos, "y"), getInt(arr, pos, "w"), getInt(arr, pos, "h"), getInt(arr, pos, "a"), pwx, pwy);
    }
    
    public static Texture getTexture(String name) {
        try {
            return TextureLoader.getTexture("PNG", new FileInputStream(getPath() + name));
        } catch (IOException ex) {
            System.err.println("There was an error to load the texture file '" + name + "': " + ex.getLocalizedMessage());
            return null;
        }
    }
    
    public static String getPath() {
        return path + "\\" + texturePacks[ct] + "\\";
    }
    
    public static void setupGray(String file) {
        gray = new Program();
        gray.addShader(ImageManager.getPath() + file);
        gray.linkProgram(); // link the shaders
        
        grayBinded = false;
    }
    
    public static void bindGray() {
        gray.bind();
        gray.defineUniform("texture"); //the texture used
        gray.setUniform("texture", 0);
        grayBinded = true;
    }
    
    public static void unbindGray() {
        gray.unbind();
        grayBinded = false;
    }
    
    public static boolean isGrayBinded() {
        return grayBinded;
    }

    public static void setGrayBinded(boolean grayBinded) {
        ImageManager.grayBinded = grayBinded;
    }
    
    public static void setupLights() {
        //lighting example !        
        FloatBuffer ambient = BufferUtils.createFloatBuffer(4);
        ambient.put(new float[] { 0.5f, 0.5f, 0.5f, 1f, });
        ambient.flip();

        FloatBuffer position = BufferUtils.createFloatBuffer(4);
        position.put(new float[] { 20f, 20f, 20f, 1f, });
        position.flip();
        
        FloatBuffer diffuse = BufferUtils.createFloatBuffer(4);
        diffuse.put(new float[] { 0.9f, 0.9f, 0.9f, 1f, });
        diffuse.flip();

        glEnable(GL_LIGHT0);
        glLightModel(GL_LIGHT_MODEL_AMBIENT, ambient);
        glLight(GL_LIGHT0, GL_POSITION, position);
        glLight(GL_LIGHT0, GL_DIFFUSE, diffuse);
    }
    
    public static void bindLights() {
        //glEnable(GL_LIGHTING);
    }
    
    public static void unbindLights() {
        //glDisable(GL_LIGHTING);
    }
}
